package com.suxin.netty.remoting;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.UUID;

/**
 * @author Tang
 * @classname RemotingCommand
 * @description [  ]
 * @date 2022/12/11 15:44
 */
@Slf4j
@Data
public class RemotingCommand {

    private static SerializeType serializeTypeServer;

    static {
        serializeTypeServer = SerializeType.JSON;
    }

    private SerializeType serializeType = serializeTypeServer;

    /**
     * code 对应 processor
     */
    private int code;

    /**
     * 一个唯一的标志，用来标志那个请求的
     */
    private String opaque;

    /**
     * 一些提示信息
     */
    private String make;

    private int version;

    private HashMap<String, String> extFields;

    private RemotingCommandType type = RemotingCommandType.REQUEST_COMMAND;

    private transient byte[] body = new byte[0];

    public RemotingCommand() {
        this.opaque = UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 快速创建一个响应
     * @param requestCode
     * @param error
     * @return
     */
    public static RemotingCommand createResponseCommand(int requestCode, String error) {
        RemotingCommand remotingCommand = new RemotingCommand();
        remotingCommand.setCode(requestCode);
        remotingCommand.setMake(error);
        remotingCommand.makeResponse();
        return remotingCommand;
    }

    public void makeRequest() {
        this.type = RemotingCommandType.REQUEST_COMMAND;
    }

    public void makeResponse() {
        this.type = RemotingCommandType.RESPONSE_COMMAND;
    }

    public boolean isResponse() {
        return this.type.equals(RemotingCommandType.RESPONSE_COMMAND);
    }

    /**
     * 解码
     * @param frame
     * @return
     */
    public static RemotingCommand decoder(ByteBuffer frame) {
        frame.flip();
        // 总长度
        int length = frame.getInt();
        log.info("length:{}",length);
        // header length
        int headerLength = frame.getInt();
        log.info("headerLength:{}",headerLength);
        // header Data
        byte[] headerData = new byte[headerLength];
        frame.get(headerData);
        RemotingCommand remotingCommand = headerDecoder(headerData);
        // body data
        byte[] bodyData = new byte[length - headerLength];
        frame.get(bodyData);
        remotingCommand.setBody(bodyData);
        return remotingCommand;
    }

    public static RemotingCommand headerDecoder(byte[] headerData) {
        if (serializeTypeServer == SerializeType.JSON) {
            return RemotingJsonSerializable.decoder(headerData,RemotingCommand.class);
        }else {
            return null;
        }
    }

    /**
     * 编码
     * @return
     */
    public ByteBuffer encodeHeader() {
        int length = 4;
        byte[] headerData;
        headerData = this.headerEncode();
        length += headerData.length;
        length += body.length;
        ByteBuffer buffer = ByteBuffer.allocate(length);
        // 总长度
        buffer.putInt(length);
        // header 长度
        buffer.putInt(headerData.length);
        // header 数据
        buffer.put(headerData);
        return buffer;
    }

    private byte[] headerEncode() {
        if (serializeType == SerializeType.JSON) {
            return RemotingJsonSerializable.encode(this);
        }else {
            return null;
        }
    }

}
